#include "server.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkInterface>
#include <QRegularExpression>
#include <QLocale>                 // ★ 解析小数用
#include <QStringList>

// —— 前置声明：onReadyRead 里要用 —— //
static bool parseSensorLine(const QByteArray& line,
                            int& hum, int& temp, int& light, int& co);

SimpleServer::SimpleServer(QObject *parent)
    : QObject(parent),
      m_server(new QTcpServer(this))
{
    connect(m_server, &QTcpServer::newConnection,
            this, &SimpleServer::onNewConnection);
}

bool SimpleServer::start(const QHostAddress& addr, quint16 port)
{
    if (!m_server->listen(addr, port)) {
        qWarning().noquote() << "[Server] listen failed:" << m_server->errorString();
        return false;
    }

    qInfo().noquote() << "[Server] listening on"
                      << m_server->serverAddress().toString()
                      << ":" << m_server->serverPort();

    // 打印本机 IPv4（便于你确认实际可连的地址）
    qInfo().noquote() << "[Server] local IPv4 addresses:";
    for (const QNetworkInterface &iface : QNetworkInterface::allInterfaces()) {
        if (!(iface.flags() & QNetworkInterface::IsUp)) continue;
        if (!(iface.flags() & QNetworkInterface::IsRunning)) continue;
        if (iface.flags() & QNetworkInterface::IsLoopBack) continue;
        for (const QNetworkAddressEntry &e : iface.addressEntries()) {
            const QHostAddress ip = e.ip();
            if (ip.protocol() == QAbstractSocket::IPv4Protocol)
                qInfo().noquote() << "  -" << ip.toString();
        }
    }
    return true;
}

void SimpleServer::onNewConnection()
{
    while (m_server->hasPendingConnections()) {
        QTcpSocket* s = m_server->nextPendingConnection();
        m_clients.insert(s);
        m_buf[s].clear();

        const QString peer  = s->peerAddress().toString()  + ":" + QString::number(s->peerPort());
        const QString local = s->localAddress().toString() + ":" + QString::number(s->localPort());
        qInfo().noquote() << "[Server] client connected from" << peer << "->" << local;
        emit clientConnected(peer, local);

        connect(s, &QTcpSocket::readyRead,    this, &SimpleServer::onReadyRead);
        connect(s, &QTcpSocket::disconnected, this, &SimpleServer::onClientDisconnected);
        connect(s, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),
                   this, &SimpleServer::onSocketError);
    }
}

// 如果 m_buf 在 .h 里是成员，就不要这一行。
// 若 .h 里没有成员 m_buf，就保留这一行作为文件内全局。
// QHash<QTcpSocket*, QByteArray> m_buf;

void SimpleServer::onReadyRead()
{
    auto sock = qobject_cast<QTcpSocket*>(sender());
    if (!sock) return;

    QByteArray& buf = m_buf[sock];
    buf += sock->readAll();

    while (true) {
        const int pos = buf.indexOf('\n');
        if (pos < 0) break;

        QByteArray line = buf.left(pos);     // 不含 '\n'
        buf.remove(0, pos + 1);

        const QString s = QString::fromUtf8(line).trimmed();
        if (s.isEmpty()) continue;

        // ★ A) 纯状态行：STATE=001010 / DEV=100001 / D=xxxxxx
        {
            static const QRegularExpression re(
                R"(^\s*(?:STATE|DEV|D)\s*=\s*([01]{6})\s*$)"
            );
            auto m = re.match(s);
            if (m.hasMatch()) {
                emit deviceBitsReceived(m.captured(1));
                continue; // 处理下一行
            }
        }

        // 传感器四个数
        int hum=0, temp=0, light=0, co=0;
        if (parseSensorLine(line, hum, temp, light, co)) {
            emit dataReceived(hum, temp, light, co);

            // ★ B) CSV 带第5列为 6 位状态：hum,temp,light,co,bits
            const QStringList parts = s.split(QRegExp("[,;\\s]+"), Qt::SkipEmptyParts);
            if (parts.size() >= 5) {
                static const QRegularExpression rebits("^[01]{6}$");
                if (rebits.match(parts.at(4)).hasMatch()) {
                    emit deviceBitsReceived(parts.at(4));
                }
            }
            continue;
        }

        qWarning().noquote() << "[Server] bad line:" << s;
    }
}

void SimpleServer::onClientDisconnected()
{
    auto sock = qobject_cast<QTcpSocket*>(sender());
    if (!sock) return;

    m_clients.remove(sock);   // ← 删掉
    m_buf.remove(sock);
    sock->deleteLater();
}



// ================== 解析实现 ==================

static bool parseSensorLine(const QByteArray& line,
                            int& hum, int& temp, int& light, int& co)
{
    const QString s = QString::fromUtf8(line).trimmed();
    if (s.isEmpty()) return false;

    // 优先用正则严格匹配 4 个数字（整数或小数，带可选正负）
    static const QRegularExpression re(
        R"(^\s*([+-]?\d+(?:\.\d+)?)\s*,\s*([+-]?\d+(?:\.\d+)?)\s*,\s*([+-]?\d+(?:\.\d+)?)\s*,\s*([+-]?\d+(?:\.\d+)?)\s*$)"
    );
    if (auto m = re.match(s); m.hasMatch()) {
        bool ok1=false, ok2=false, ok3=false, ok4=false;
        const double v1 = QLocale::c().toDouble(m.captured(1), &ok1);
        const double v2 = QLocale::c().toDouble(m.captured(2), &ok2);
        const double v3 = QLocale::c().toDouble(m.captured(3), &ok3);
        const double v4 = QLocale::c().toDouble(m.captured(4), &ok4);
        if (ok1 && ok2 && ok3 && ok4) {
            hum   = qRound(v1);
            temp  = qRound(v2);
            light = qRound(v3);
            co   = qRound(v4);
            return true;
        }
    }

    // 兜底：按逗号切分再逐个 toDouble（容错更强）
    QStringList parts = s.split(',', Qt::KeepEmptyParts);
    // 去掉纯空白片段
    for (int i = parts.size()-1; i >= 0; --i) {
        if (parts[i].trimmed().isEmpty())
            parts.removeAt(i);
        else
            parts[i] = parts[i].trimmed();
    }
    if (parts.size() < 4) return false;

    bool ok1=false, ok2=false, ok3=false, ok4=false;
    const double v1 = QLocale::c().toDouble(parts[0], &ok1);
    const double v2 = QLocale::c().toDouble(parts[1], &ok2);
    const double v3 = QLocale::c().toDouble(parts[2], &ok3);
    const double v4 = QLocale::c().toDouble(parts[3], &ok4);
    if (!(ok1 && ok2 && ok3 && ok4)) return false;

    hum   = qRound(v1);
    temp  = qRound(v2);
    light = qRound(v3);
    co   = qRound(v4);
    return true;
}

// —— 成员包装：有人在别处调用 SimpleServer::parseLine(...) 时，链接就不再报缺符号 —— //
bool SimpleServer::parseLine(const QByteArray& line,
                             int& hum, int& temp, int& light, int& co)
{
    return parseSensorLine(line, hum, temp, light, co);
}

// === 修改后：不使用 std::as_const，改用 const 迭代器 ===
int SimpleServer::sendRawToAll(const QByteArray& data, bool addNewline)
{
    QByteArray payload = data;
    if (addNewline && (payload.isEmpty() || payload.back() != '\n'))
        payload.append('\n');

    int okCount = 0;

    for (auto it = m_clients.cbegin(); it != m_clients.cend(); ++it) {
        QTcpSocket* s = *it;
        if (!s) continue;
        if (s->state() != QAbstractSocket::ConnectedState) continue;

        const qint64 n = s->write(payload);
        if (n == payload.size()) okCount++;
    }

    qInfo().noquote() << "[Server] broadcast bytes:" << payload.size()
                      << "to" << okCount << "client(s).";
    return okCount;
}

int SimpleServer::sendCsvToAll(int hum, int temp, int light, int co, bool addNewline)
{
    QByteArray line = QByteArray::number(hum) + "," +
                      QByteArray::number(temp) + "," +
                      QByteArray::number(light) + "," +
                      QByteArray::number(co);
    return sendRawToAll(line, addNewline);
}

void SimpleServer::onSocketError(QAbstractSocket::SocketError /*err*/)
{
    auto sock = qobject_cast<QTcpSocket*>(sender());
    if (!sock) return;

    qWarning().noquote() << "[Server] socket error:" << sock->errorString();

    // 彻底清理该连接
    m_clients.remove(sock);
    m_buf.remove(sock);
    sock->deleteLater();
}

